package com.imooc.miaoshaproject.service.impl;

import com.imooc.miaoshaproject.mapper.ItemDOMapper;
import com.imooc.miaoshaproject.po.ItemPO;
import com.imooc.miaoshaproject.po.ItemStockPO;
import com.imooc.miaoshaproject.exceptions.ServiceException;
import com.imooc.miaoshaproject.exceptions.ErrorCodeEnum;
import com.imooc.miaoshaproject.service.model.ItemModel;
import com.imooc.miaoshaproject.service.model.PromoModel;
import com.imooc.miaoshaproject.validator.ValidatorImpl;
import com.imooc.miaoshaproject.mapper.ItemStockDOMapper;
import com.imooc.miaoshaproject.service.ItemService;
import com.imooc.miaoshaproject.service.PromoService;
import com.imooc.miaoshaproject.validator.ValidationResult;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class ItemServiceImpl implements ItemService {

    private final ValidatorImpl validator;

    private final ItemDOMapper itemDOMapper;

    private final PromoService promoService;

    private final ItemStockDOMapper itemStockDOMapper;

    public ItemServiceImpl(ItemStockDOMapper itemStockDOMapper, PromoService promoService, ItemDOMapper itemDOMapper, ValidatorImpl validator) {
        this.itemStockDOMapper = itemStockDOMapper;
        this.promoService = promoService;
        this.itemDOMapper = itemDOMapper;
        this.validator = validator;
    }

    @Override
    @Transactional
    public ItemModel createItem(ItemModel itemModel) throws ServiceException {
        //校验入参
        ValidationResult result = validator.validate(itemModel);
        if (result.isHasErrors()) {
            throw new ServiceException(ErrorCodeEnum.PARAMETER_VALIDATION_ERROR, result.getErrMsg());
        }

        ItemPO itemPO = this.convertItemDOFromItemModel(itemModel);
        itemDOMapper.insertSelective(itemPO);

        itemModel.setId(itemPO.getId());
        ItemStockPO itemStockPO = this.convertItemStockDOFromItemModel(itemModel);
        itemStockDOMapper.insertSelective(itemStockPO);
        return this.getItemById(itemModel.getId());
    }

    private ItemPO convertItemDOFromItemModel(ItemModel itemModel) {
        if (itemModel == null) {
            return null;
        }
        ItemPO itemPO = new ItemPO();
        BeanUtils.copyProperties(itemModel, itemPO);
        itemPO.setPrice(itemModel.getPrice().doubleValue());
        return itemPO;
    }

    private ItemStockPO convertItemStockDOFromItemModel(ItemModel itemModel) {
        if (itemModel == null) {
            return null;
        }
        ItemStockPO itemStockPO = new ItemStockPO();
        itemStockPO.setItemId(itemModel.getId());
        itemStockPO.setStock(itemModel.getStock());
        return itemStockPO;
    }

    @Override
    public List<ItemModel> listItem() {
        List<ItemPO> itemPOList = itemDOMapper.listItem();
        List<ItemModel> itemModelList = itemPOList.stream().map(itemPO -> {
            ItemStockPO itemStockPO = itemStockDOMapper.selectByItemId(itemPO.getId());
            ItemModel itemModel = this.convertModelFromDataObject(itemPO, itemStockPO);
            return itemModel;
        }).collect(Collectors.toList());
        return itemModelList;
    }

    @Override
    public ItemModel getItemById(Integer id) {
        ItemPO itemPO = itemDOMapper.selectByPrimaryKey(id);
        if (itemPO == null) {
            return null;
        }
        ItemStockPO itemStockPO = itemStockDOMapper.selectByItemId(itemPO.getId());
        ItemModel itemModel = convertModelFromDataObject(itemPO, itemStockPO);
        PromoModel promoModel = promoService.getPromoByItemId(itemModel.getId());
        if (promoModel != null && promoModel.getStatus() != 3) {
            itemModel.setPromoModel(promoModel);
        }
        return itemModel;
    }

    @Override
    @Transactional
    public boolean decreaseStock(Integer itemId, Integer amount) throws ServiceException {
        int affectedRow = itemStockDOMapper.decreaseStock(itemId, amount);
        return affectedRow > 0;
    }

    @Override
    @Transactional
    public void increaseSales(Integer itemId, Integer amount) throws ServiceException {
        itemDOMapper.increaseSales(itemId, amount);
    }

    private ItemModel convertModelFromDataObject(ItemPO itemPO, ItemStockPO itemStockPO) {
        ItemModel itemModel = new ItemModel();
        BeanUtils.copyProperties(itemPO, itemModel);
        itemModel.setPrice(new BigDecimal(itemPO.getPrice()));
        itemModel.setStock(itemStockPO.getStock());
        return itemModel;
    }
}
